PersisterBuilderPipeline.java
package org.codefilarete.stalactite.engine.configurer.builder;
import java.util.Map;
import org.codefilarete.stalactite.dsl.entity.EntityMappingConfiguration;
import org.codefilarete.stalactite.engine.PersisterRegistry;
import org.codefilarete.stalactite.engine.configurer.AbstractIdentification;
import org.codefilarete.stalactite.engine.configurer.NamingConfiguration;
import org.codefilarete.stalactite.engine.configurer.NamingConfigurationCollector;
import org.codefilarete.stalactite.engine.configurer.builder.InheritanceMappingStep.Mapping;
import org.codefilarete.stalactite.engine.configurer.builder.InheritanceMappingStep.MappingPerTable;
import org.codefilarete.stalactite.engine.runtime.ConfiguredRelationalPersister;
import org.codefilarete.stalactite.engine.runtime.SimpleRelationalEntityPersister;
import org.codefilarete.stalactite.sql.ConnectionConfiguration;
import org.codefilarete.stalactite.sql.Dialect;
import org.codefilarete.stalactite.sql.ddl.structure.PrimaryKey;
import org.codefilarete.stalactite.sql.ddl.structure.Table;
import static org.codefilarete.tool.collection.Iterables.first;
public class PersisterBuilderPipeline<C, I> {
private final TableLookupStep<C, I> tableLookupStep;
private final TableMappingStep<C, I> tableMappingStep;
private final IdentificationStep<C, I> identificationStep;
private final InheritanceMappingStep<C, I> inheritanceMappingStep;
private final PrimaryKeyStep<C, I> primaryKeyStep;
private final PrimaryKeyPropagationStep<C, I> primaryKeyPropagationStep;
private final IdentifierManagerStep<C, I> identifierManagerStep;
private final MainPersisterStep<C, I> mainPersisterStep;
private final RelationsStep<C, I> relationsStep;
private final PolymorphismStep<C, I> polymorphismStep;
private final AlreadyAssignedMarkerStep<C, I> alreadyAssignedMarkerStep;
private final ParentPersistersStep<C, I> parentPersistersStep;
private final Dialect dialect;
private final ConnectionConfiguration connectionConfiguration;
private final PersisterRegistry persisterRegistry;
private PersisterBuilderContext persisterBuilderContext;
public PersisterBuilderPipeline(Dialect dialect, ConnectionConfiguration connectionConfiguration, PersisterRegistry persisterRegistry) {
this.dialect = dialect;
this.connectionConfiguration = connectionConfiguration;
this.tableLookupStep = new TableLookupStep<>();
this.tableMappingStep = new TableMappingStep<>();
this.identificationStep = new IdentificationStep<>();
this.inheritanceMappingStep = new InheritanceMappingStep<>();
this.primaryKeyStep = new PrimaryKeyStep<>();
this.primaryKeyPropagationStep = new PrimaryKeyPropagationStep<>();
this.identifierManagerStep = new IdentifierManagerStep<>();
this.mainPersisterStep = new MainPersisterStep<>();
this.relationsStep = new RelationsStep<>();
this.polymorphismStep = new PolymorphismStep<>();
this.alreadyAssignedMarkerStep = new AlreadyAssignedMarkerStep<>();
this.parentPersistersStep = new ParentPersistersStep<>();
this.persisterRegistry = persisterRegistry;
}
public ConfiguredRelationalPersister<C, I> build(EntityMappingConfiguration<C, I> entityMappingConfiguration) {
persisterBuilderContext = PersisterBuilderContext.CURRENT.get();
boolean isInitiator = false;
if (persisterBuilderContext == null) {
persisterBuilderContext = new PersisterBuilderContext(persisterRegistry);
PersisterBuilderContext.CURRENT.set(persisterBuilderContext);
isInitiator = true;
}
try {
ConfiguredRelationalPersister<C, I> result = doBuild(entityMappingConfiguration);
// making aggregate persister available for external usage
persisterRegistry.addPersister(result);
if (isInitiator) {
// This if is only there to execute code below only once, at the very end of persistence graph build,
// even if it could seem counterintuitive since it compares "isInitiator" whereas this comment talks about end of graph :
// because persistence configuration is made with a deep-first algorithm, this code (after doBuild()) will be called at the very end.
persisterBuilderContext.getBuildLifeCycleListeners().forEach(BuildLifeCycleListener::afterBuild);
persisterBuilderContext.getBuildLifeCycleListeners().forEach(BuildLifeCycleListener::afterAllBuild);
}
return result;
} finally {
if (isInitiator) {
PersisterBuilderContext.CURRENT.remove();
}
}
}
private ConfiguredRelationalPersister<C, I> doBuild(EntityMappingConfiguration<C, I> entityMappingConfiguration) {
NamingConfigurationCollector namingConfigurationCollector = new NamingConfigurationCollector(entityMappingConfiguration);
NamingConfiguration namingConfiguration = namingConfigurationCollector.collect();
Table table = tableLookupStep.lookupForTable(entityMappingConfiguration, namingConfiguration.getTableNamingStrategy());
Map<EntityMappingConfiguration, Table> entityMappingConfigurationTables = tableMappingStep.mapEntityConfigurationToTable(entityMappingConfiguration,
table,
namingConfiguration.getTableNamingStrategy());
AbstractIdentification<C, I> identification = identificationStep.determineIdentification(entityMappingConfiguration);
MappingPerTable<C> inheritanceMappingPerTable = inheritanceMappingStep.collectPropertiesMappingFromInheritance(entityMappingConfiguration,
entityMappingConfigurationTables,
dialect.getColumnBinderRegistry(),
namingConfiguration.getColumnNamingStrategy(),
namingConfiguration.getIndexNamingStrategy());
PrimaryKey<?, I> primaryKey = primaryKeyStep.addIdentifyingPrimarykey(identification,
entityMappingConfigurationTables,
dialect.getColumnBinderRegistry(),
namingConfiguration.getColumnNamingStrategy(),
namingConfiguration.getIndexNamingStrategy());
primaryKeyPropagationStep.propagate(primaryKey, inheritanceMappingPerTable, namingConfiguration.getForeignKeyNamingStrategy());
// determining insertion manager must be done AFTER primary key addition, else it would fall into NullPointerException
identifierManagerStep.applyIdentifierManager(identification, inheritanceMappingPerTable, identification.getIdAccessor(), dialect, connectionConfiguration);
SimpleRelationalEntityPersister<C, I, ?> mainPersister = mainPersisterStep.buildMainPersister(
entityMappingConfiguration,
identification,
inheritanceMappingPerTable,
namingConfiguration,
dialect,
connectionConfiguration);
relationsStep.configureRelations(mainPersister, inheritanceMappingPerTable, persisterBuilderContext, namingConfiguration, dialect, connectionConfiguration);
ConfiguredRelationalPersister<C, I> result = polymorphismStep.eventuallyTransformToPolymorphicPersister(mainPersister,
entityMappingConfiguration,
identification,
(Mapping<C, ?>) first(inheritanceMappingPerTable.getMappings()),
namingConfiguration,
dialect,
connectionConfiguration,
persisterBuilderContext);
alreadyAssignedMarkerStep.handleAlreadyAssignedMarker(result);
parentPersistersStep.buildParentPersisters(mainPersister, identification, inheritanceMappingPerTable, dialect, connectionConfiguration);
return result;
}
}